/*@@

	Copyright (c) 2010 BlueSky LTD. All rights reserved. 

	Created_datetime : 	2010-6-21

	File Name :	base_packmgr.h

	Author : liusiliang (siliangliu@msn.com)

	Description : 

@@*/

#ifndef __BASE_PACKMGR_H__
#define __BASE_PACKMGR_H__

//////////////////////////////////////////////////////////////////////////
//						Header Include
//////////////////////////////////////////////////////////////////////////

#include "blk_def.h"
#include "blk_stl.h"

namespace BLK
{
	//////////////////////////////////////////////////////////////////////////
	//		Global variables and Macro and Structure Definitions
	//////////////////////////////////////////////////////////////////////////

	//包文件的压缩方式
	enum PackCompressMethod
	{
		TYPE_NONE	= 0x00000000,			//没有压缩
		TYPE_UCL	= 0x01000000,			//UCL压缩
		TYPE_BZIP2	= 0x02000000,			//bzip2压缩
		TYPE_ZLIB	= 0x04000000,			//zlib压缩

		TYPE_METHOD_FILTER	= 0x0f000000,	//过滤标记
		TYPE_FILTER			= 0xff000000,	//过滤标记
	};

	//	使用XPackFile对子文件进行访问操作所用到的辅助结构
	struct PackElemFileRef
	{
		unsigned long	uId;			//文件id
		int				nPackIndex;		//包索引
		int				nElemIndex;		//包内的子文件索引
		int				nCacheIndex;	//缓冲索引
		int				nOffset;		//子文件的操作便移动
		int				nSize;			//子文件的大小
	};

	//////////////////////////////////////////////////////////////////////////
	//
	//						Class Declare
	//
	//////////////////////////////////////////////////////////////////////////

	struct PackIndexInfo;
	struct PackElemFileRef;
	class XPackFile;

	class PackMgr
	{
	public:

		/*
		 *	功能:	析构函数
		 */
		~PackMgr(void);

		/*
		 *	功能:	单件
		 */
		static PackMgr& Singleton(void)
		{
			static PackMgr packMgr;
			return packMgr;
		}

	public:

		/*
		 *	功能:	打开读入一系列包（先清空）
		 *	参数:	FileList	包路径的列表
		 *	返回:	是否读入成功
		 */
		bool LoadPackList(const std::vector<std::string>& FileList);

		/*
		 *	功能:	删除所有包
		 */
		void UnLoad(void);

		/*
		 *	功能:	查找包内的子文件
		 *	参数:	uId	--> 子文件的路径ID
		 *			ElemRef	--> 用于存放（传出）文件信息
		 *	返回:	是否找到子文件
		 */
		bool FindElemFile(
			unsigned long uId,
			PackElemFileRef& ElemRef);

		/*
		 *	功能:	在所有包中扫描指定文件
		 *	参数:	pszFileName	--> 文件名
		 *			ElemRef	-->	用于存放（传出）文件信息
		 *	返回:	是否成功找到
		 */
		bool FindElemFile(
			const char* pszFileName, 
			PackElemFileRef& ElemRef);

		/*
		 *	功能:	读取包内的子文件
		 *	参数:	ElemRef --> 用来读取数据的参数
		 *			pBuffer --> 用来读取数据的缓冲区
		 *			uSize --> 要读取的数据的长度
		 *	返回:	成功读取得字节数
		 */
		int	ElemFileRead(
			PackElemFileRef& ElemRef, 
			void* pBuffer, 
			unsigned uSize);

		/*
		 *	功能:	打包文件夹
		 *	参数:	PackFileName	打包文件路径名称
		 *			WorkingPath		打包工作目录
		 *	返回:	是否打包成功
		 */
		static bool Pack(
			const std::string& strPackFile,
			const std::string& strDir);

		/*
		 *	功能:	打包文件
		 *	参数:	PackFileName	打包文件路径名称
		 *			WorkingPath		打包工作目录
		 *			vFileList		需要打包的 子文件路径+名称 列表
		 *	返回:	是否打包成功
		 */
		static bool Pack(
			const std::string& strPackFileName,
			const std::string& strWorkingPath,
			const std::vector<std::string>& vFileList);
		
		/*
		 *	功能:	解包文件成子文件
		 *	参数:	FileName	包文件名
		 *			DestPath	解包到目标路径
		 *			bOverwrite	是否覆盖解压文件
		 *	返回:	解包是否成功
		 */
		static bool UnPack(
			const std::string& FileName, 
			const std::string& DestPath,
			bool bOverwrite = false);

	private:

		/*
		 *	功能:	构造函数
		 */
		PackMgr(void);
		
		/*
		 *	功能:	把文件名转换为包中的id
		 *	参数:	pszFileName	文件名
		 *	返回:	文件名对应的包中的id
		 */
		static unsigned long FileNameToId(const char* pszFileName);
		
		/*
		 *	功能:	打开一个包文件
		 *	参数:	szFile	文件名
		 *			nIndex	PACK索引
		 *	返回:	是否打开成功
		 */
		bool LoadPack(
			const char* szFile, 
			int nIndex);

		/*
		 *	功能:	取得文件在压缩包中的路径名
		 *	参数:	lpPathName	路径名
		 *			lpFileName	文件名
		 */
		void GetPackPath(
			char* lpPathName, 
			const char* lpFileName);

		/*
		 *	功能:	包是否存在
		 *	参数:	strFileName	包文件名
		 *	返回:	是否存在此名字的包
		 */
		bool IsPackExist(const std::string& strFileName);

		static bool IsDirExist(const std::string& strDir);

		static void MakeFileList(const std::string& strDir);

		/*
		 *	功能:	打包单个文件
		 *	参数:	pFileBuf			输入文件缓存
		 *			OutFile				输出文件流
		 *			FileInfo			记录文件信息
		 *			ulFileDataOffset	打包信息位置
		 *	返回:	压缩后的大小
		 */
		static unsigned	PackElemFile(
			const void*			pFileBuf,
			std::ofstream&		OutFile,
			PackIndexInfo&		FileInfo,
			unsigned long&		ulFileInfoOffset);

		/*
		 *	功能:	解包一个文件
		 *	参数:	InFile		输入文件流
		 *			OutFile		输出文件流
		 *			FileInfo	文件信息
		 *	返回:	是否解包成功
		 */
		static bool	UnPackElemFile(
			std::ifstream& InFile,
			std::ofstream& OutFile,
			const PackIndexInfo& FileInfo);
		
		/*
		 *	功能:	根据文件名返回压缩类型
		 *	参数:	FileName	文件名
		 *	返回:	压缩类型
		 */
		static PackCompressMethod GetFileCompressType(const std::string& FileName);

		static void FileCallBack(
			const std::string& strFile, 
			void* pArgs);

	private:

		typedef std::vector<XPackFile*> PackFileList;
		PackFileList		m_PackFileList;			//	包文件列表

		static int						ms_nDirLen;
		static std::vector<std::string> ms_vFileName;
	};

};

#endif
